import React, { useState } from 'react';
import {
  List,
  ListItem,
  TextField,
  ListItemIcon,
  ListItemText,
  Box,
} from '@mui/material';
import { FolderOpen as FolderOpenIcon } from '@mui/icons-material';
import ActionDialog from './ActionDialog';
import Tooltip from '../../general/Tooltip';
import FileBrowser from '../../general/FileBrowser';
import Checkbox from '../../general/Checkbox';
import { registerModelPath } from '../../../redux/slices/generalSlice';
import { useAppDispatch } from '../../../redux/hooks';

const loadOptions = [
  {
    label: 'High-level Network Parameters (netParams)',
    label2: 'Cell rules, connectivity rules, etc',
    state: 'loadNetParams',
  },
  {
    label: 'Simulation Configuration (simConfig)',
    label2: 'duration, recorded variables, etc',
    state: 'loadSimCfg',
  },
  {
    label: 'Instantiated Network',
    label2: 'All cells, connections, etc',
    state: 'loadNet',
  },
  {
    label: 'Simulation Data',
    label2: 'Spikes, traces, etc',
    state: 'loadSimData',
  },
];

interface LoadFileDialogProps {
  open?: boolean;
  onRequestClose?: () => void;
  [key: string]: any;
}

/**
 * LoadFileDialog Component
 * Dialog for loading JSON model files with options for what to load
 */
const LoadFileDialog: React.FC<LoadFileDialogProps> = ({
  open = false,
  onRequestClose,
  ...otherProps
}) => {
  const dispatch = useAppDispatch();
  const [jsonModelFolder, setJsonModelFolder] = useState('');
  const [modFolder, setModFolder] = useState('');
  const [compileMod, setCompileMod] = useState(false);
  const [explorerDialogOpen, setExplorerDialogOpen] = useState(false);
  const [explorerParameter, setExplorerParameter] = useState('');
  const [exploreOnlyDirs, setExploreOnlyDirs] = useState(false);
  const [areModFieldsRequired, setAreModFieldsRequired] = useState<boolean | undefined>(undefined);
  const [jsonPath, setJsonPath] = useState('');
  const [modPath, setModPath] = useState('');
  const [loadNetParams, setLoadNetParams] = useState(true);
  const [loadSimCfg, setLoadSimCfg] = useState(true);
  const [loadSimData, setLoadSimData] = useState(true);
  const [loadNet, setLoadNet] = useState(true);

  const showExplorerDialog = (param: string, onlyDirs: boolean): void => {
    setExplorerDialogOpen(true);
    setExplorerParameter(param);
    setExploreOnlyDirs(onlyDirs);
  };

  const closeExplorerDialog = (fieldValue?: any): void => {
    setExplorerDialogOpen(false);
    if (fieldValue) {
      const fileName = fieldValue.path.replace(/^.*[\\/]/, '');
      const path = fieldValue.path
        .split(fileName)
        .slice(0, -1)
        .join('');
      if (explorerParameter === 'modFolder') {
        setModFolder(fieldValue.path);
        setModPath(path);
        dispatch(registerModelPath(path));
      } else if (explorerParameter === 'jsonModelFolder') {
        setJsonModelFolder(fieldValue.path);
        setJsonPath(path);
        dispatch(registerModelPath(path));
      }
    }
  };

  const isFormValid = (): boolean => {
    return areModFieldsRequired !== undefined && areModFieldsRequired !== false;
  };

  const freezeInstance = !!loadNet;
  const freezeSimulation = !!(freezeInstance && loadSimData);
  const tab = loadSimData || loadNet ? 'simulate' : 'define';

  const toggleLoadOption = (state: string): void => {
    switch (state) {
      case 'loadNetParams':
        setLoadNetParams((prev) => !prev);
        break;
      case 'loadSimCfg':
        setLoadSimCfg((prev) => !prev);
        break;
      case 'loadSimData':
        setLoadSimData((prev) => !prev);
        break;
      case 'loadNet':
        setLoadNet((prev) => !prev);
        break;
    }
  };

  return (
    <>
      <ActionDialog
        title="Open JSON file"
        buttonLabel="Load"
        message="LOADING FILE"
        isFormValid={isFormValid}
        command="netpyne_geppetto.loadModel"
        args={{
          jsonModelFolder,
          modFolder,
          compileMod,
          jsonPath,
          modPath,
          loadNetParams,
          loadSimCfg,
          loadSimData,
          loadNet,
          tab,
          freezeInstance,
          freezeSimulation,
        }}
        open={open}
        onRequestClose={onRequestClose}
        {...otherProps}
      >
        <Box>
          <Box display="flex" alignItems="center">
            <Tooltip title="File explorer" placement="top">
              <FolderOpenIcon
                sx={{
                  cursor: 'pointer',
                  mr: 1,
                  '&:hover': { opacity: 0.7 },
                }}
                onClick={() => showExplorerDialog('jsonModelFolder', false)}
              />
            </Tooltip>
            <TextField
              fullWidth
              variant="filled"
              label="JSON file"
              value={jsonModelFolder}
              onChange={(e) => setJsonModelFolder(e.target.value)}
              helperText={jsonPath !== '' ? `path: ${jsonPath}` : ''}
              sx={{
                '& .MuiFilledInput-root': {
                  '&::before': {
                    display: 'none',
                  },
                },
              }}
            />
          </Box>
          <Box pl={3}>
            <List
              sx={{
                display: 'flex',
                flexWrap: 'wrap',
              }}
            >
              {loadOptions.map((loadOption, index) => {
                const isChecked =
                  loadOption.state === 'loadNetParams' ? loadNetParams :
                  loadOption.state === 'loadSimCfg' ? loadSimCfg :
                  loadOption.state === 'loadNet' ? loadNet :
                  loadSimData;
                return (
                  <ListItem key={index} sx={{ width: '50%' }}>
                    <ListItemIcon>
                      <Checkbox
                        onChange={() => toggleLoadOption(loadOption.state)}
                        checked={isChecked}
                        noBackground
                      />
                    </ListItemIcon>
                    <ListItemText
                      primary={loadOption.label}
                      secondary={loadOption.label2}
                      sx={{
                        '& .MuiListItemText-primary': isChecked ? {} : {
                          opacity: 0.6,
                        },
                      }}
                    />
                  </ListItem>
                );
              })}
            </List>
          </Box>
          <Box display="flex" alignItems="center" sx={{ mt: 2 }}>
            <Box width="50%" display="flex" alignItems="center">
              <Tooltip title="File explorer" placement="top">
                <FolderOpenIcon
                  sx={{
                    cursor: 'pointer',
                    mr: 1,
                    '&:hover': { opacity: 0.7 },
                  }}
                  onClick={() => showExplorerDialog('modFolder', true)}
                />
              </Tooltip>
              <TextField
                variant="filled"
                fullWidth
                label="Mod folder"
                value={modFolder}
                onChange={(e) => setModFolder(e.target.value)}
                sx={{
                  '& .MuiFilledInput-root': {
                    '&::before': {
                      display: 'none',
                    },
                  },
                }}
              />
            </Box>
            <Box width="50%" pl={3.5}>
              <Checkbox
                fullWidth
                noBackground
                label="Compile mod files"
                checked={compileMod}
                onChange={() => setCompileMod((prev) => !prev)}
              />
            </Box>
          </Box>
        </Box>
      </ActionDialog>

      <FileBrowser
        open={explorerDialogOpen}
        exploreOnlyDirs={exploreOnlyDirs}
        filterFiles=".json"
        onRequestClose={closeExplorerDialog}
      />
    </>
  );
};

export default LoadFileDialog;

